import pika
from typing import Optional, Callable
from app.core.config import settings

class RabbitMQClient:
    """RabbitMQ客户端类
    
    封装RabbitMQ操作，提供简化的接口用于消息队列操作
    基于pika库实现
    """
    def __init__(self):
        """初始化RabbitMQ连接参数
        
        根据配置创建RabbitMQ连接参数
        """
        self.credentials = pika.PlainCredentials(
            settings.RABBITMQ_USER,
            settings.RABBITMQ_PASSWORD
        )
        self.parameters = pika.ConnectionParameters(
            host=settings.RABBITMQ_HOST,
            port=settings.RABBITMQ_PORT,
            virtual_host=settings.RABBITMQ_VHOST,
            credentials=self.credentials
        )
        self.connection = None
        self.channel = None

    def connect(self) -> None:
        """建立RabbitMQ连接
        
        如果连接不存在或已关闭，则创建新连接和通道
        """
        if not self.connection or self.connection.is_closed:
            self.connection = pika.BlockingConnection(self.parameters)
            self.channel = self.connection.channel()

    def close(self) -> None:
        """关闭RabbitMQ连接
        
        如果连接存在且未关闭，则关闭连接
        """
        if self.connection and not self.connection.is_closed:
            self.connection.close()

    def publish(self, exchange: str, routing_key: str, body: str,
                exchange_type: str = 'direct') -> None:
        """发布消息
        
        向指定的交换机发布消息
        
        Args:
            exchange: 交换机名称
            routing_key: 路由键
            body: 消息内容
            exchange_type: 交换机类型，默认为direct
        """
        try:
            self.connect()
            self.channel.exchange_declare(
                exchange=exchange,
                exchange_type=exchange_type
            )
            self.channel.basic_publish(
                exchange=exchange,
                routing_key=routing_key,
                body=body
            )
        finally:
            self.close()

    def consume(self, queue: str, callback: Callable,
                exchange: str = '', routing_key: str = '',
                exchange_type: str = 'direct') -> None:
        """消费消息
        
        从指定队列消费消息，并通过回调函数处理
        
        Args:
            queue: 队列名称
            callback: 消息处理回调函数
            exchange: 交换机名称，如为空则直接使用队列
            routing_key: 路由键
            exchange_type: 交换机类型，默认为direct
        """
        try:
            self.connect()
            if exchange:
                self.channel.exchange_declare(
                    exchange=exchange,
                    exchange_type=exchange_type
                )
                self.channel.queue_declare(queue=queue)
                self.channel.queue_bind(
                    queue=queue,
                    exchange=exchange,
                    routing_key=routing_key
                )
            else:
                self.channel.queue_declare(queue=queue)

            self.channel.basic_consume(
                queue=queue,
                on_message_callback=callback,
                auto_ack=True
            )
            self.channel.start_consuming()
        finally:
            self.close()

# 创建全局RabbitMQ客户端实例
rabbitmq_client = RabbitMQClient()